#ifndef DRV_CTRB_C
#define DRV_CTRB_C

#include <linux/types.h>
#include <linux/kdev_t.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/cdev.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
#include <linux/slab.h>
#include <linux/device.h>
#include <../arch/arm/mach-s3c2410/include/mach/regs-gpio.h>
#include <../arch/arm/mach-s3c2410/include/mach/hardware.h>

#include "drv_ctrb.h"

#define CONF(p,d)	s3c2410_gpio_cfgpin((p),(d))
#define SET(p,d)	s3c2410_gpio_setpin((p),(d))
#define GET(p)		s3c2410_gpio_getpin((p))

#define		FAN				S3C2410_GPG3		//eint11
#define		FAN_IN			S3C2410_GPG3_INP
#define		FAN_OUT			S3C2410_GPG3_OUTP
#define		S_HOT				S3C2410_GPG0		//eint8
#define		S_HOT_IN			S3C2410_GPG0_INP
#define		S_HOT_OUT			S3C2410_GPG0_OUTP
#define		S_COLD				S3C2410_GPG6		//eint14
#define		S_COLD_IN			S3C2410_GPG6_INP
#define		S_COLD_OUT			S3C2410_GPG6_OUTP
#define		S_COLD2				S3C2410_GPG11		//eint19
#define		S_COLD2_IN			S3C2410_GPG11_INP
#define		S_COLD2_OUT			S3C2410_GPG11_OUTP
#define		LIGHT1_C			S3C2410_GPG1	//eint9
#define		LIGHT1_C_IN			S3C2410_GPG1_INP
#define		LIGHT1_C_OUT		S3C2410_GPG1_OUTP
#define		LIGHT2_C			S3C2410_GPG7		//eint15
#define		LIGHT2_C_IN			S3C2410_GPG7_INP
#define		LIGHT2_C_OUT		S3C2410_GPG7_OUTP
#define		LIGHT3_C			S3C2410_GPG10		//eint18
#define		LIGHT3_C_IN			S3C2410_GPG10_INP
#define		LIGHT3_C_OUT		S3C2410_GPG10_OUTP
#define		HUMI_C				S3C2410_GPG5		//eint13
#define		HUMI_C_IN			S3C2410_GPG5_INP
#define		HUMI_C_OUT			S3C2410_GPG5_OUTP

#if 0
#define		FAN_ON			0x00
#define		FAN_OFF			0x01
#define		COLD_ON			0x02
#define		HOT_ON			0x03
#define		STOP				0x04
#define		LIGHT1_ON		0x08
#define		LIGHT1_OFF		0x09
#define		LIGHT2_ON		0x0a
#define		LIGHT2_OFF		0x0b
#define		LIGHT3_ON		0x0c
#define		LIGHT3_OFF		0x0d
#define		HUMI_ON			0x0e
#define		HUMI_OFF		0x0f
#endif

#define MY_MAJOR	248
#define MY_MINOR	0
#define MY_COUNT	1
#define MY_NAME	"HW_CTRB"


static int ctrb_major,ctrb_minor;
static dev_t ctrb_dev;
static struct cdev *ctrb_cdev;
static int ctrb_open (struct inode *i, struct file *f);
static int ctrb_ioctl(struct inode *i,struct file *f,unsigned int cmd,unsigned long l);
static int ctrb_startup();
static struct class *ctrb_class;

static Ctrb_State ctrb_state;

static int ctrb_startup()
{
	CONF(S_HOT,S_HOT_OUT);
	CONF(S_COLD,S_COLD_OUT);
	CONF(S_COLD2,S_COLD2_OUT);
	CONF(LIGHT1_C,LIGHT1_C_OUT);
	CONF(LIGHT2_C,LIGHT2_C_OUT);
	CONF(LIGHT3_C,LIGHT3_C_OUT);
	CONF(HUMI_C,HUMI_C_OUT);	
	CONF(FAN,FAN_OUT);
	SET(FAN,0);
	SET(S_HOT,1);
	SET(S_COLD,1);	
	SET(S_COLD2,1);
	SET(LIGHT1_C,0);
	SET(LIGHT2_C,0);
	SET(LIGHT3_C,0);
	SET(HUMI_C,0);	
	
	ctrb_state.s_fan=S_SWITCH_OFF;
	ctrb_state.s_humi=S_SWITCH_OFF;
	ctrb_state.s_light1=S_SWITCH_OFF;
	ctrb_state.s_light2=S_SWITCH_OFF;
	ctrb_state.s_light3=S_SWITCH_OFF;
	ctrb_state.s_core=S_CORE_OFF;
	
	return 1;
}

static int ctrb_open(struct inode *node, struct file *file)
{
	printk("ctrb opened!\n");
	return 0;
}

static int ctrb_ioctl(struct inode *i,struct file *f,unsigned int cmd,unsigned long l)
{
	switch(cmd)
	{
		case CMD_FAN_ON:
			SET(FAN,1);
			ctrb_state.s_fan=S_SWITCH_ON;
			break;		
		case CMD_FAN_OFF:
			SET(FAN,0);
			ctrb_state.s_fan=S_SWITCH_OFF;
			break;
		case CMD_COLD_ON:
			SET(S_COLD,0);
			SET(S_COLD2,0);
			SET(S_HOT,1);
			ctrb_state.s_core=S_COLD;
			break;
		case CMD_HOT_ON:
			SET(S_HOT,0);
			SET(S_COLD,1);	
			SET(S_COLD2,1);
			ctrb_state.s_core=S_CORE_HOT;
			break;
		case CMD_ALL_OFF:
			SET(S_HOT,1);
			SET(S_COLD,1);	
			SET(S_COLD2,1);
			ctrb_state.s_core=S_CORE_OFF;
			break;
		case CMD_LIGHT1_ON:
			SET(LIGHT1_C,1);
			ctrb_state.s_light1=S_SWITCH_ON;
			break;
		case CMD_LIGHT1_OFF:
			SET(LIGHT1_C,0);
			ctrb_state.s_light1=S_SWITCH_OFF;
			break;
		case CMD_LIGHT2_ON:
			SET(LIGHT2_C,1);
			ctrb_state.s_light2=S_SWITCH_ON;
			break;
		case CMD_LIGHT2_OFF:
			SET(LIGHT2_C,0);
			ctrb_state.s_light2=S_SWITCH_OFF;
			break;
		case CMD_LIGHT3_ON:
			SET(LIGHT3_C,1);
			ctrb_state.s_light3=S_SWITCH_ON;
			break;
		case CMD_LIGHT3_OFF:
			SET(LIGHT3_C,0);
			ctrb_state.s_light3=S_SWITCH_OFF;
			break;
		case CMD_HUMI_ON:
			SET(HUMI_C,1);
			ctrb_state.s_humi=S_SWITCH_ON;
			break;
		case CMD_HUMI_OFF:
			SET(HUMI_C,0);
			ctrb_state.s_humi=S_SWITCH_OFF;
			break;
		default:
			return 1;
	}
	return 0;
}

static ssize_t ctrb_read(struct file *filp, char *buffer,size_t count, loff_t *ppos)
{
	return copy_to_user(buffer,&ctrb_state,sizeof(ctrb_state));
}


static struct file_operations ctrb_fops = {
  .owner = THIS_MODULE,
  .open = ctrb_open,
  .read = ctrb_read,
  .ioctl= ctrb_ioctl,
};

static int __init ctrb_init(void)
{
	int r;
//assign device's major and minor!!
	if(MY_MAJOR)
	{
		ctrb_dev=MKDEV(MY_MAJOR,MY_MINOR);
		r=register_chrdev_region(ctrb_dev,MY_COUNT,MY_NAME);
	}
	if(r<0)
		r=alloc_chrdev_region(&ctrb_dev, MY_MINOR, MY_COUNT, MY_NAME);
	ctrb_major=MAJOR(ctrb_dev);
	ctrb_minor=MINOR(ctrb_dev);

	if(r<0)
	{
		printk(KERN_WARNING "Can't get major !!\n");
		return r;
	}
	else
		printk("The major is %d, and the minor is %d!\n",ctrb_major,ctrb_minor);
//assign device's major and minor!!

//register char device	
	ctrb_cdev= cdev_alloc();
	if(ctrb_cdev!=NULL)
	{
		cdev_init(ctrb_cdev, &ctrb_fops);
		ctrb_cdev->ops = &ctrb_fops;
		ctrb_cdev->owner=THIS_MODULE;	
	 	r=cdev_add(ctrb_cdev, ctrb_dev, MY_COUNT);	
	 	
 		if(r)
		{
			printk(KERN_NOTICE "Error %d adding CTRB", r);
			return 1;
		}
		else
		{
			ctrb_class = class_create(THIS_MODULE, MY_NAME);
			if(IS_ERR(ctrb_class))
			{
				 printk("Err: failed in ctrb class. \n");
				 return 1;
			}
			device_create(ctrb_class, NULL, MKDEV(ctrb_major, 0), NULL, MY_NAME);
			printk(KERN_NOTICE "Adding Luyx_ctrb is successfully!!\n");
			ctrb_startup();
			return 0;
		}	
	}
	else
	{
		printk(KERN_NOTICE "Error %d adding CTRB", r);
		return 1;
	}
//register char device	
}

static void __exit ctrb_exit(void)
{
	cdev_del(ctrb_cdev);
	unregister_chrdev_region(ctrb_dev, MY_COUNT);	
	device_destroy(ctrb_class, MKDEV(ctrb_major, 0));
	class_destroy(ctrb_class);
	printk(KERN_ALERT "Goodbye, cruel world\n");
}

module_init(ctrb_init);
module_exit(ctrb_exit);
MODULE_DESCRIPTION("CTRB driver for hw");
MODULE_LICENSE("GPL");

#endif
